# @Time : 2020/7/28 18:01
# @Author : Fioman 
# @Phone : 13149920693
import cv2 as cv
import numpy as np

"""
比较两个轮廓最简单的方法就是比较两者的轮廓矩.轮廓矩代表了一个轮廓,一幅图像,一组点集的全局特征.矩信息包含了对应对象不同类型的几何特征,
例如,大小,位置,角度,形状等.矩特征被广泛地应用在模式识别,图像识别等方面.
矩的计算: moments函数
我们将使用函数cv.moments()获取的轮廓特征称为"轮廓矩".轮廓矩描述了一个轮廓的重要特征,使用轮廓矩可以方便地比较两个轮廓.
retval = cv.moments(array[,binaryImage])
array: 可以是点集,也可以是灰度图像或二值图像.当array是点集时,函数会把这些点集当作轮廓中的顶点,把整个点集作为一条轮廓,
而不是把它们当成独立的点来看待.

binaryImage: 该参数是True时,array内所有的非零值都被处理为1.该参数只有当参数array为图像的时候有效.

该函数的返回值: retval,主要包含如下:
1> 空间矩

2> 中心矩

4> 归一化中心矩

在Opencv中,函数cv.moments()会同时计算上述空间矩,中心矩和归一化中心矩.

例如:
如果有两个轮廓,不管它们出现在图像上的哪个位置,我们都可以通过函数cv.moments()的m00矩判断其面积是否一致.
在位置发生变化时,虽然轮廓的面积,周长特征不变,但是更高阶的特征会随着位置的变化而发生变化.在很多情况下,我们希望比较不同位置的两个对象的一致性.
解决这个问题的方法就是引入中心矩.中心矩通过减去均值而获得平移不变性,因而能够比较不同位置的两个对象是否一致.很明显,中心矩具有平移不变性,使它能够忽略两个
对象的位置关系,帮助我们比较不同位置上两个对象的一致性.

归一化中心矩通过除以物体总尺寸而获得缩放不变性.它通过上述计算提取对象的归一化中心矩属性值,该属性值不仅具有平移不变性,还具有缩放不变性.
"""

img = cv.imread("moments.jpg", cv.IMREAD_COLOR)[2:,:-3]
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

T, thresOtsu = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
image,contours,hierarchy = cv.findContours(thresOtsu,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
n = len(contours)
contourImg = []
for i in range(n):
    temp = np.zeros(img.shape,np.uint8)
    contourImg.append(temp)
    contourImg[i] = cv.drawContours(contourImg[i],contours,i,(0,255,0),1)
    cv.imshow("contours[{}]".format(i),contourImg[i])

print("观察各个轮廓的矩(moments):")
for i in range(n):
    print("轮廓 {} 的矩:".format(cv.moments(contours[i])))

for i in range(n):
    print("轮廓 {} 的面积: {}".format(i,cv.moments(contours[i])["m00"]))

cv.waitKey(0)
cv.destroyAllWindows()
































